﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using HotChocolate;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;

namespace CRM.Models.Email;

[Index(nameof(State))]
[Index(nameof(Type))]
[Index(nameof(TimingTransmission))]
// 联合索引,用于后台发送邮件
[Index(nameof(State), nameof(Type), nameof(TimingTransmission))]
[Index(nameof(OemId), nameof(CompanyId), nameof(GroupId), nameof(UserId))]
public class EmailMarketing : BaseModel, IEquatable<EmailMarketing>
{
    [Comment("id")]
    public int Id { get; set; }

    [Comment("UserId")]
    public int UserId { get; set; }

    [Comment("GroupId")]
    public int GroupId { get; set; }

    [Comment("CompanyId")]
    public int CompanyId { get; set; }

    [Comment("OemId")]
    public int OemId { get; set; }

    [Comment("营销任务名称")]
    [Column(TypeName = "varchar(50)")]
    public string Title { get; set; }

    [Comment("状态:1未提交 2已经提交 3已取消 4已完成")]
    [Column(TypeName = "tinyint")]
    public StateEnum State { get; set; }
    public enum StateEnum
    {
        UnSubmit = 1,
        Submitted = 2,
        Canceled = 3,
        Completed = 4
    }

    [Comment("是否锁定")]
    public bool IsLocked { get; set; } = false;

    [Comment("类型:1服务 2免费")]
    public TypeEnum Type { get; set; }
    public enum TypeEnum
    {
        Server = 1,
        Free = 2
    }

    /// <summary>
    /// 需要发送的总数量, 发送失败数为`SubmitNum - SendingNum`
    /// </summary>
    [Comment("提交数")]
    public int SubmitNum { get; set; }

    /// <summary>
    /// 发送成功数
    /// </summary>
    [Comment("发送数")]
    public int SendingNum { get; set; }

    [Comment("打开数")]
    public int OpenNum { get; set; }

    [Comment("回复数")]
    public int ReplyNum { get; set; }

    [Comment("发件人")]
    [Column(TypeName = "json")]
    public string Addresser { get; set; }
    [NotMapped]
    public List<EmailConfig> AddresserObj => JsonConvert.DeserializeObject<List<EmailConfig>>(Addresser);

    [Comment("回复邮箱")]
    [Column(TypeName = "varchar(50)")]
    public string ReplyEmail { get; set; }

    [Comment("是否显示为发件邮箱")]
    public bool ShowAsEmail { get; set; }

    [Comment("收件人")]
    [Column(TypeName = "json")]
    public string Addressee { get; set; }
    [NotMapped]
    public List<AddresseeObj> AddresseeObj => JsonConvert.DeserializeObject<List<AddresseeObj>>(Addressee);
        
    [Comment("收件人")]
    [Column(TypeName = "json"), MaxLength(100), GraphQLIgnore]
    public string? FreeEmailSetting { get; set; }
    [NotMapped, GraphQLName("freeEmailSetting")]
    public FreeEmailSetting FreeEmailSettingObj => JsonConvert.DeserializeObject<FreeEmailSetting>(FreeEmailSetting ?? "{}");

    [Comment("邮件主题")]
    [Column(TypeName = "text")]
    public string EmailSubject { get; set; }

    // 可以垂直拆分出去
    [Comment("附件")]
    [Column(TypeName = "json")]
    public string Attachment { get; set; }

    // 可以垂直拆分出去
    [Comment("邮件内容")]
    public string EmailContent { get; set; }

    [Comment("定时发送")]
    public DateTime TimingTransmission { get; set; }

    [JsonIgnore]
    public Collection<Customer> Customers { get; set; }

    [DefaultValue(EmailPlatform.Mailjet), Comment("邮件发送平台")]
    public EmailPlatform EmailPlatform { get; set; }

    /// <summary>
    /// 邮件发件人名称id
    /// </summary>
    [Comment("邮件发件人名称id")]
    public int? EmailSenderNameId { get; set; }

    public EmailSenderName? EmailSenderName { get; set; }
    /// <summary>
    /// 邮件模板id数组
    /// </summary>
    [Comment("邮件模板id数组")]
    public string EmailTemplateIds { get; set; }


    /// <summary>
    /// 修改状态
    /// </summary>
    /// <param name="state"></param>
    public void SetState(StateEnum state)
    {
        State = state;
    }

    public bool Equals(EmailMarketing other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return Id == other.Id && UserId == other.UserId && GroupId == other.GroupId && CompanyId == other.CompanyId && OemId == other.OemId && Title == other.Title && State == other.State && IsLocked == other.IsLocked && Type == other.Type && SubmitNum == other.SubmitNum && SendingNum == other.SendingNum && OpenNum == other.OpenNum && ReplyNum == other.ReplyNum && Addresser == other.Addresser && ReplyEmail == other.ReplyEmail && ShowAsEmail == other.ShowAsEmail && Addressee == other.Addressee && EmailSubject == other.EmailSubject && Attachment == other.Attachment && EmailContent == other.EmailContent && TimingTransmission.Equals(other.TimingTransmission) && Equals(Customers, other.Customers) && EmailPlatform == other.EmailPlatform;
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != this.GetType()) return false;
        return Equals((EmailMarketing)obj);
    }

    public override int GetHashCode()
    {
        var hashCode = new HashCode();
        hashCode.Add(Id);
        hashCode.Add(UserId);
        hashCode.Add(GroupId);
        hashCode.Add(CompanyId);
        hashCode.Add(OemId);
        hashCode.Add(Title);
        hashCode.Add((int)State);
        hashCode.Add((int)Type);
        hashCode.Add(SubmitNum);
        hashCode.Add(SendingNum);
        hashCode.Add(OpenNum);
        hashCode.Add(ReplyNum);
        hashCode.Add(Addresser);
        hashCode.Add(ReplyEmail);
        hashCode.Add(ShowAsEmail);
        hashCode.Add(Addressee);
        hashCode.Add(EmailSubject);
        hashCode.Add(Attachment);
        hashCode.Add(EmailContent);
        hashCode.Add(TimingTransmission);
        hashCode.Add((int)EmailPlatform);
        return hashCode.ToHashCode();
    }
}

public class AddresseeObj
{
    public string Addressee { get; set; }
    public string Name { get; set; }
    public int? Id { get; set; }
    public bool IsRead { get; set; }
    public bool IsReply { get; set; }
    public bool IsFailed { get; set; }
}

public class FreeEmailSetting
{
    public int MinSendInterval { get; set; }
    public int MaxSendInterval { get; set; }
    public SendMethod SendMethod { get; set; }
    public SendMethod SendTemplateMethod { get; set; }
    public bool TrackReadStatus { get; set; }
}

public enum EmailPlatform
{
    Mailjet,
    Rushmail,
}

public enum SendMethod
{
    Random,
    Asc,
}